package com.iwat.spring.aop.aspect;

import com.alibaba.fastjson.JSON;
import com.iwat.spring.aop.annotation.OperLog;
import com.iwat.spring.aop.entity.SysLog;
import com.iwat.spring.aop.service.LogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 系统日志：切面处理类
 *
 * @Author wangwiqiang
 */
@Slf4j
@Aspect
@Component
public class SysLogAspect {

    @Autowired
    private LogService logService;

    /**
     * 定义切点 @Pointcut
     * 在注解的位置切入代码
     */
    @Pointcut("@annotation(com.iwat.spring.aop.annotation.OperLog)")
    public void logPoint() {
    }

    /**
     * @param proceedingJoinPoint
     * @return
     * @Around：环绕通知
     */
    @Around("logPoint()")
    public Object saveSysLog(ProceedingJoinPoint proceedingJoinPoint) {

        //开始计时
        long start = System.currentTimeMillis();
        SysLog sysLog = new SysLog();
        sysLog.setCreateDate(new Date());

        MethodSignature signature = null;
        //从切面织入点处通过反射机制获取织入点处的方法
        if (proceedingJoinPoint.getSignature() instanceof MethodSignature) {
            signature = (MethodSignature) proceedingJoinPoint.getSignature();
        }
        //获取切入点所在的方法
        Method method = signature.getMethod();

        //获取操作
        OperLog myLog = method.getAnnotation(OperLog.class);
        if (myLog != null) {
            String value = myLog.message();
            sysLog.setMessage(value);
        }

        //设置请求的方法名
        sysLog.setMethod(signature.getMethod().toString());

        //设置请求的参数
        Object[] args = proceedingJoinPoint.getArgs();
        String params = JSON.toJSONString(args);
        sysLog.setParams(params);

        //todo 获取用户名


        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        //记录url
        String urlReg = "//(.*?)(/.*)";
        Pattern r = Pattern.compile(urlReg);
        Matcher m = r.matcher(request.getRequestURL().toString());
        if (m.find()) {
            sysLog.setUrl(m.group(2));
        }
        sysLog.setType(request.getMethod());
        sysLog.setIp(request.getRemoteAddr());

        try {
            // 执行原方法，proceedingJoinPoint本身就是一个拦截到的方法的签名
            Object result = proceedingJoinPoint.proceed();
            //计算所用时间
            Long time = System.currentTimeMillis() - start;
            sysLog.setTotalTime(time);
            //保存SysLog实体类到数据库
            logService.save(sysLog);

            return result;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return new HashMap<String, Object>() {{
            put("msg", "error");
        }};
    }
}

